package com.cn.lxz.lot.http

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.Response
import java.lang.reflect.Type

class HttpFunction {
    private constructor()

    companion object{
        inline fun  <reified T> Flow<Response>.mapGson(): Flow<T> {
            val type: Type = object : TypeToken<T>() {}.type
            val gson = Gson()

            return map { response ->
                val result = response.body?.string()?:""
                Log.e("http",result)
                val data:T = gson.fromJson(result,type)
                data
            }
        }

        inline fun  <reified T> Flow<Response>.mapStringGson(crossinline action:(String)->String): Flow<T> {
            val type: Type = object : TypeToken<T>() {}.type
            val gson = Gson()

            return map { response ->
                val result = response.body?.string()?:""
                var change = action.invoke(result)
                val data:T = gson.fromJson(change,type)
                data
            }
        }

        suspend inline fun  <reified T> Flow<Response>.runMapGson(crossinline callBack:(T)->Unit):Unit {
            val map = mapGson<T>()
            map.collect{
                callBack.invoke(it)
            }
        }

        inline fun  <reified T> Flow<Response>.baseBeanMapGson(): Flow<BaseBean<T>> {
            val type: Type = object : TypeToken<BaseBean<T>>() {}.type
            val gson = Gson()

            return map { response ->
                val result = response.body?.string()
                val data:BaseBean<T> = gson.fromJson(result,type)
                data
            }
        }
        val viewModelScope = object: ViewModel() {};
        inline fun  <reified T> Flow<Response>.baseBeanMapGson(
            crossinline onError:(Throwable)->Unit,
            crossinline callBack:(T)->Unit):Unit {
            val flow = baseBeanMapGson<T>()
                .map {
                    if(it.code!=0){
                        throw Exception(it.code.toString())
                    }
                    it.data
                }
                .map {
                    if(it==null){
                        throw NullPointerException()
                    }
                    it
                }
                .catch {
                    withContext(Dispatchers.IO) {
                      onError.invoke(it)
                    }
                }
              viewModelScope.viewModelScope.launch {
                flow.collect{
                    callBack.invoke(it)
                }
              }

        }


    }
}